//
// Created by LONG on 2020/11/12.
//

#include "l1IntfDl.h"
#include "../../../l3Intf/include/l3IntfDef.h"

void UE_L2_L1I_DL_PotUeProcess(S_UeL2UeInst *pUeInst)
{
    int32_t rc;
    uint32_t size;
    uint32_t needSendInd;
    S_UeCommMsgHdr *pCommMsgHdr;
    S_OsSelectInd indMsg;

    needSendInd = FALSE;
    while (1)
    {
        pCommMsgHdr = VarRB_ReadRequest(pUeInst->pL1L2CpMsgQue, &size);
        IF_BREAK(==, NULL, pCommMsgHdr, NO_LOG_MESSAGE);

        switch (pCommMsgHdr->type)
        {
        case UE_L1_API_MSG_CONFIG_RSP:
            CSP_LOG_INF(UE_MD_L2_L1I, "UE_L2_L1I_DL_PotUeProcess() recv UE_L1_API_MSG_CONFIG_RSP\n");
            VRB_PUT(rc, gpUeL2Context->pL1iL3iMsgQue, pCommMsgHdr, pCommMsgHdr->size);
            break;
        case UE_L1_API_MSG_SYNC_RSP:
            CSP_LOG_INF(UE_MD_L2_L1I, "UE_L2_L1I_DL_PotUeProcess() recv UE_L1_API_MSG_SYNC_RSP\n");
            VRB_PUT(rc, gpUeL2Context->pL1iL3iMsgQue, pCommMsgHdr, pCommMsgHdr->size);
            break;
        default:
            CSP_LOG_WRN(UE_MD_L2_L1I, "UE_L2_L1I_DL_PotUeProcess() recv unsupport msg[%#x]\n", pCommMsgHdr->type);
            break;
        }
        VarRB_ReadConsume(pUeInst->pL1L2CpMsgQue, pCommMsgHdr);
        needSendInd = TRUE;
    }
    if (needSendInd)
    {
        indMsg.ind = UE_L2_INTRA_IND_MSG_L1_RSP_MSG;
        OS_SelectSend(&gpUeL2L3IntfContext->selector, &indMsg);
    }
}

void UE_L2_L1I_DL_TtiUeProcess(S_UeL2UeInst *pUeInst)
{
    int32_t rc;
    uint32_t size;
    S_UeCommMsgHdr *pCommMsgHdr;

    while (1)
    {
        pCommMsgHdr = VarRB_ReadRequest(pUeInst->pL1L2UpMsgQue, &size);
        IF_BREAK(==, NULL, pCommMsgHdr, NO_LOG_MESSAGE);

        switch (pCommMsgHdr->type)
        {
        case UE_L1_API_MSG_SLOT_IND:
        {
            uint32_t sfnSlot;
            S_UeL1ApiMsgSlotInd *pSlotInd;
            pSlotInd = (S_UeL1ApiMsgSlotInd *)pCommMsgHdr;
            if (pUeInst->currAirSfnSlot.sfn != pSlotInd->sfn || pUeInst->currAirSfnSlot.slot != pSlotInd->slot)
            {
                CSP_LOG_WRN(UE_MD_L2_L1I, "UE_L2_L1I_DL_TtiUeProcess() sfn is not coutinue! old[%u, %u], new[%u, %u]\n",
                    pUeInst->currAirSfnSlot.sfn, pUeInst->currAirSfnSlot.slot, pSlotInd->sfn, pSlotInd->slot);
            }
            pUeInst->currAirSfnSlot.sfn = pSlotInd->sfn;
            pUeInst->currAirSfnSlot.slot = pSlotInd->slot;
            O5G_SfnSlot_Add(&pUeInst->currAirSfnSlot.sfn, &pUeInst->currAirSfnSlot.slot, pUeInst->slotNum, 1);

            LOG_UpdateTick((uint64_t)pUeInst->currAirSfnSlot.sfn << 8 | pUeInst->currAirSfnSlot.slot);

//            CSP_LOG_INF(UE_MD_L2_L1I, "UE_L2_L1I_DL_TtiUeProcess() recv UE_L1_API_MSG_SLOT_IND [%u, %u]\n", pSlotInd->sfn, pSlotInd->slot);

//            UE_L2_L1I_UL_WakeUp(pUeInst);
        }
            break;
        default:
            CSP_LOG_WRN(UE_MD_L2_L1I, "UE_L2_L1I_DL_TtiUeProcess() recv unsupport msg[%#x]\n", pCommMsgHdr->type);
            break;
        }
        VarRB_ReadConsume(pUeInst->pL1L2UpMsgQue, pCommMsgHdr);
    }
}

void UE_L2_L1I_DL_TtiProcess(int32_t event, int fd, void *data)
{
    uint32_t ueLoop;
    S_UeL2UeInst *pUeInst;

    pUeInst = (S_UeL2UeInst *)data;

    UE_L2_L1I_DL_TtiUeProcess(pUeInst);

    for (ueLoop = 0; ueLoop < UE_UE_INST_NUM_MAX; ueLoop++)
    {
        pUeInst = &gpUeL2Context->ueInst[ueLoop];
        IF_CONTINUE(==, FALSE, pUeInst->inUse, NO_LOG_MESSAGE);

        UE_L2_L1I_DL_PotUeProcess(pUeInst);
    }
}

void UE_L2_L1I_DL_PtoProcess()
{
    uint32_t ueLoop;
    S_UeL2UeInst *pUeInst;

    for (ueLoop = 0; ueLoop < UE_UE_INST_NUM_MAX; ueLoop++)
    {
        pUeInst = &gpUeL2Context->ueInst[ueLoop];
        IF_CONTINUE(==, FALSE, pUeInst->inUse, NO_LOG_MESSAGE);

        UE_L2_L1I_DL_PotUeProcess(pUeInst);
    }
}

void *UE_L2_L1I_DL_Task(void* arg)
{
    int fd;
    int32_t rc;
    uint32_t ueLoop;
    S_UeL2UeInst *pUeInst;

    for (ueLoop = 0; ueLoop < UE_UE_INST_NUM_MAX; ueLoop++)
    {
        pUeInst = &gpUeL2Context->ueInst[ueLoop];
        IF_CONTINUE(==, FALSE, pUeInst->inUse, NO_LOG_MESSAGE);

        fd = pUeInst->ttiIntSelector.recvFd;
        POLLER_Add(gpUeL2L1IntfContext->dlPoller, fd, UE_L2_L1I_DL_TtiProcess, NULL, NULL, pUeInst);
    }

    while (1)
    {
        rc = POLLER_Poll(gpUeL2L1IntfContext->dlPoller, 10);
        if (0 == rc)
        {
            /*
             * POLL TIME OUT处理，是为了在L1 START前处理能够处理L3等消息。
             * L1 START后就会有TTI消息上来，就不会超时进入此分支。
             */
            UE_L2_L1I_DL_PtoProcess();
        }
        pthread_testcancel();
    }
    return NULL;
}
